;	PDP-11 FLOATING POINT PACKAGE
;	ASCII STRING TO FLOATING POINT FORMAT CONVERSION
;	FLOATING POINT FORMAT TO ASCII STRING CONVERSION
;
;	MODULES INCLUDED:
;	1. ATOF
;	2. FTOA
;	3. ETOA
;
;
;
;
R0	=	%0
R1	=	%1
R2	=	%2
R3	=	%3
R4	=	%4
R5	=	%5
SP	=	%6
PC	=	%7
ATOF:	MOV	#M.TEN-.-6,R2	;GET THE RELATIVE ADDRESS OF 10.
	ADD	PC,R2		;COMPUTE THE ABSOLUTE ADDRESS
	MOV	R2,-(SP)	;PUSH IT ON THE STACK FOR LATER
	MOV	R0,-(SP)	;SAVE THE DEFA
	CLR	(R0)+		;CLEAR HIGH ORDER FRACTION
	CLR	(R0)+		;CLEAR LOW ORDER FRACTION
	CLR	@R0		;CLEAR THE EXPONENT
	CLR	-(SP)		;CLEAR EXP1
	CLR	-(SP)		;CLEAR EXP2
	CLR	-(SP)		;CLEAR THE SWITCHES
M.AFXN:	MOVB	(R1)+,R2	;GET A CHARACTER FRON THE INPUT STRING
	BIC	#177600,R2	;GET RID OF ALL THE UNUSED BITS
	CMPB	#105,R2		;LOOK FOR AN E
	BEQ	M.AFE		;BRANCH IF AN E IS FOUND
	CMPB	#55,R2		;LOOK FOR A MINUS
	BEQ	M.AFMI		;BRANCH IF A MINUS SIGN
	CMPB	#53,R2		;LOOK FOR A PLUS
	BEQ	M.AFPL		;BRANCH IF A PLUS SIGN
	CMPB	#56,R2		;LOOK FOR A DECIMAL POINT
	BEQ	M.AFD		;BRANCH IF A DECIMAL POINT
	CMPB	#40,R2		;LOOK FOR A <SP>
	BEQ	M.AFSP		;BRANCH IF A SPACE
	CMPB	#15,R2		;LOOK FOR A <CR>
	BEQ	M.AFXT		;BRANCH IF A CARRIAGE RETURN
	CMPB	#54,R2		;LOOK FOR A COMMA
	BEQ	M.AFXT		;BRANCH IF A COMMA
	CMPB	#60,R2		;LOOK FOR A 0
	BGT	M.AFVS		;ERROR IS SMALLER THATN 0
	CMPB	#71,R2		;LOOK FOR A 9
	BLT	M.AFVS		;ERROR IF CHARACTER IS LARGER THAN 9
	SUB	#60,R2		;CONVERT TO A BINARY NUMBER
	MOV	R1,-(SP)	;SAVE THE SEFA
	BIT	#4,2(SP)	;TEST THE E SWITCH
	BNE	M.AFXP		;BRANCH IF COLLECTING EXPONENT
	SUB	#6,SP		;PUT A FLOATING POINT NUMBER ON STACK
	MOV	SP,R0		;SET UP THE DEFA FOR FLT
	MOV	R2,-(SP)	;PUSH THE NUMBER ON THE STACK
	MOV	SP,R1		;SET UP THE SEFA FOR FLT
	JSR	PC,FLT		;FLOAT THE INTEGER
	TST	(SP)+		;REMOVE UNNEEDED STACK ROOM
	MOV	16(SP),R0	;GET THE DEFA
	MOV	20(SP),R1	;GET THE ADDRESS OF 10.
	JSR	PC,MULF		;MULTIPLY BY 10.
	BVS	M.AFVT		;OVERFLOW IS A NO-NO
	MOV	16(SP),R0	;FIX UP THE DEFA POINTER
	MOV	SP,R1		;SET UP THE SEFA POINTER
	JSR	PC,ADDF		;ADD THE CURRENT DIGIT
	BIT	#10,10(SP)	;TEST THE D SWITCH
	BEQ	.+6	;->	;IF ZERO DON'T TOUCH EXP2
	DEC	12(SP)	;  I	;DECREMENT EXP2
	ADD	#6,SP	;<-	;CLEAR UP THE STACK
M.AFSS:	MOV	(SP)+,R1	;PICK UP THE SEFA
	BIS	#1,@SP		;SET THE S SWITCH
	BR	M.AFNX		;GO GET MORE STUFF
M.AFXP:	MOV	R2,-(SP)	;PUSH THE CURRENT DIGIT
	MOV	10(SP),R3	;GET THE OLD EXPONENT
	MOV	#12,R5		;PUT DECIMAL 10 IN R5
	CLR	R2		;CLEAR REGISTERS FOR
	CLR	R4		;THE BIG MULTIPLY
	CMP	R3,#980.	;CHECK FOR A HUGE EXPONENT
	BGT	M.AFVU		;IF TOO BIG TELL HIM
	JSR	PC,M.DPIM	;MULTIPLY BY TEN
	ADD	(SP)+,R3	;ADD THE CURRENT DIGIT
	MOV	R3,6(SP)	;SAVE IT BACK ON THE STACK
	BR	M.AFSS		;SET S SWITCH
M.AFE:	BIT	#4,@SP		;SEE IF THSI IS THE FIRST E
	BNE	M.AFVS		;ERROR IF MORE THAN ONE E
	BIS	#4,@SP		;SET THE E SWITCH
	BIT	#1,@SP		;SEE IF WE EVEN HAD A FRACTION
	BEQ	M.AFVS		;BRANCH WITH NO FRACTION
	BIC	#11,@SP		;CLEAR THE S AND D SWITCHES
	BR	M.AFNX		;GET THE NEXT CHARACTER
M.AFD:	BIT	#14,@SP		;TEST E AND D SWITCHES
	BNE	M.AFVS		;EITHER ONE SET IS AN ERRROR
	BIS	#10,@SP		;SET THE D SWITCH
	BR	M.AFNX		;SET START OF SIGNIFICANCE
M.AFPL:	BIC	#400,@SP	;CLEAR THE M SWITCH
	BR	.+4	;->	;SKIP THE NEXT INSTRUCTION
M.AFMI:	BIS	#400,@SP;  I	;SET THE M SWITCH
	BIT	#4,@SP	;<-	;TEST THE E SWITCH
	BNE	M.AFSE		;BRANCH IF SIGN OF THE EXPONENT
	BIT	#31,@SP		;TEST THE A, D, AND S SWITCHES
	BNE	M.AFVS		;IF EITHER IS SET AN ERROR IS HERE
	BIS	#20,@SP		;SET THE A SWITCH
	BIT	#400,@SP	;TEST IF A MINUS SIGN
	BEQ	M.AFNX		;RETURN IF PLUS SIGN
	BIS	#100,@SP	;SET MINUS SIGN
	BR	M.AFNX		;GET THE NEXT CHARACTER
M.AFXT:	BR	M.AFTX		;DARN 11 BRANCHES THAT GO NO
M.AFNX:	BR	M.AFXN		;FURTHER THAN 128 WORDS
M.AFSE:	BIT	#51,@SP		;TEST THE B, D, AND S SWITCHES
	BNE	M.AFVS		;ERROR IF EITHER IS SET
	BIS	#40,@SP		;SET THE B SWITCH
	BIT	#400,@SP	;TEST FOR A MINUS SIGN
	BEQ	M.AFNX		;EXIT IF A PLUS
	BIS	#200,@SP	;SET MINUS EXPONENT
	BR	M.AFNX		;GET NEXT CHARACTER
M.AFSP:	BIT	#11,@SP		;TEST FOR START OF SIGNIFICANCE OR DEC PT
	BEQ	M.AFNX		;IF NONE IGNORE SPACES
M.AFX1:	MOVB	(R1)+,R2	;GET THE NEXT CHARACTER
	BIC	#177600,R2	;REMOVE ALL THATS NOT OURS
	CMPB	#40,R2		;SEE IF ITS A SPACE ALSO
	BEQ	M.AFX1		;BRANCH FOR MORE IF A SPACE
	CMPB	#15,R2		;IF NOT A SPACE THEN A <CR> ?
	BEQ	M.AFXT		;BRANCH IF A CARRIAGE RETURN
	CMPB	#54,R2		;COMMAS ARE ALSO LEGAL
	BEQ	M.AFXT		;BRANCH TO FINISH UP
M.AFVS:	BIS	#2,@SP		;SET THE V SWITCH
	BR	M.AFX1		;GO GET THE NEXT CHARACTER
M.AFVT:	ADD	#10,SP		;REMOVE 8 WORDS FROM THE STACK
	BR	M.AFVS		;SET V AND EXIT
M.AFVU:	CMP	(SP)+,(SP)+	;POP ONE WORD OFF THE STACK
	BR	M.AFVS		;SET V AND EXIT
M.AFVV:	BIS	#2,@SP		;SET V AND QUIT
	BR	M.AFX5		;BYPASS ALL ELSE
M.AFTX:	TST	@SP		;IF NO SWITCHES THEN OK
	BEQ	M.AFX6		;SKIP SIGNIFICANCE TEST
	BIT	#1,@SP		;TEST SIGNIFICANCE MUST HAVE IT
	BNE	M.AFX6		;EXIT WITH ERROR
	BIS	#2,@SP		;SET OVERFLOW FOR LATTER
M.AFX6:	MOV	R1,-(SP)	;SAVE THE SOURCE POINTER
	BIT	#100,2(SP)	;SEE IF IT SHOULD BE NEGATIVE
	BEQ	M.AFX2		;BRANCH OF NO CONVERSION
	MOV	10(SP),R0	;PICK UP DEFA
	MOV	R0,R1		;MAKE SEFA=DEFA
	JSR	PC,NEGF		;NEGATE THE NUMBER
M.AFX2:	BIT	#200,2(SP)	;SEE IF A NEGATIVE EXPONENT
	BEQ	M.AFX3		;BRANCH IF NO NEGATION
	NEG	6(SP)		;NEGATE THE EXPONENT
	BVC	M.AFX3		;TEST FOR VALID EXPONTNE
	BIS	#2,2(SP)	;SET THE V BIT
	BR	M.AFX5		;EXIT WITH ERROR
M.AFX3:	ADD	4(SP),6(SP)	;REMEMBER ANY DECIMAL PLACES
	BEQ	M.AFX5		;BRANCH IF NO CONVERSION
	BVS	M.AFVV		;IF OVERFLOW SET AND EXIT
	BLT	M.AFDV		;IF LESS THEN ZERO DIVIDE
M.AFX4:	MOV	10(SP),R0	;SET UP DEFA=#
	MOV	12(SP),R1	;SET UP SEFA=10.
	JSR	PC,MULF		;MULTIPLY BY 10.
	DEC	6(SP)		;DECREMENT AND TEST
	BGT	M.AFX4		;FOR DONE
	BR	M.AFX5		;BYPAS DIVIDE SECTION
M.AFDV:	MOV	10(SP),R0	;SET UP DEFA=#
	MOV	12(SP),R1	;SET UP SEFA=10.
	JSR	PC,DIVF		;DIVIDE BY 10.
	INC	6(SP)		;INCREMENT AND TEST
	BLT	M.AFDV		;FOR COMPLETION 
M.AFX5:	MOV	(SP)+,R1	;RESTORE THE SOURCE POINTER
	MOV	(SP)+,R4	;SAVE THE SIWTCHES
	ADD	#10,SP		;REMOVE 4 MORE WORDS FORM THE STACK
	BIT	#2,R4		;TEST FOR V SETTING
	BNE	.+4	;->
	RTS	PC	;  I	;NORMAL RETURN
	SEV		;<-
	RTS	PC		;ERROR RETURN
M.TEN:	.WORD	0,050000,100004	;FLOATING POINT 10.
	.WORD	0,040000,100001	;FLOATING POINT 1.
	.WORD	040000,046113,100030	;FLOATING POINT 10.^7
	.WORD	0,040000,100000	;FLOATING POINT .5
FTOA:	CLR	-(SP)		;CLEAR SWITCHES AND SET F TYPE
	MOV	#13,R2		;MOVE DECIMAL 11 TO COUNTER
	BR	M.XA0		;COMBINE WITH ETOA FOR A WHILE
ETOA:	CLR	-(SP)		;CLEAR ALL SWITCHES
	INC	@SP		;SET E TYPE CONVERSION
	MOV	#17,R2		;MOVE DECIMAL 15 TO THE COUNTER
M.XA0:	MOV	R0,-(SP)	;SAVE THE DEFA
	CLR	-(SP)		;ZERO OUT THE DECIMAL EXPONENT
	MOVB	#040,(R0)+	;<-	;ENTER SPACES IN OUTPUT AREA
	DEC	R2		;  I	;DECREMENT COUNTER
	BGT	.-6		;->	;BRANCH IF NOT DONE
	MOV	#M.TEN-.-6,R2	;GET RELATIVE LOCATION OF THE CONSTANTS
	ADD	PC,R2		;ADD RELOCATION FACTOR
	MOV	#6,R3		;LENGTH OF A FLOATING POINT NUMBER
	MOV	#4,R4		;NUMBER OF CONSTANTS IN THE TABLE
	MOV	R2,-(SP);<-	;STORE AN ADDRESS ON THE STACK
	ADD	R3,R2	;  I	;COMPUTE NEXT ADDRESS
	DEC	R4	;  I	;DECREMENT COUNTER
	BGT	.-6	;->	;BRANCH IF MORE TO DO
	SUB	R3,SP		;PUT A SPACE FOR THE NUMBER
	MOV	SP,R0		;SET UP THE DEFA FOR THE MOVE
	JSR	PC,MOVF		;MOVE OUR NUMBER TO THE STACK
	TST	2(SP)		;TEST FOR ZERO
	BNE	M.XA1		;BRANCH IF RANGING IS REQUIRED
	MOV	20(SP),R0	;PICK UP THE DEFA
	ADD	#2,R0		;GO TO POSITION 3
	MOV	#10,R2		;EIGHT IS THE NUMBER OF ZEROS
	MOVB	#060,(R0)+	;<-	MOVE AN ASCII 0
	DEC	R2		;  I	;DECREMENT COUNTER
	BGT	.-6		;->	BRANCH OF NOT COMPLETED
	DEC	16(SP)		;ADJUST THE EXPONENT FOR THE REST
	TST	22(SP)		;TEST FOR TYPE OF CONVERSION
	BNE	M.XA6		;BRANCH IF E TYPE COMVERSION
	INC	16(SP)		;MOVE DECIMAL POINT ONE RIGHT FOR F TYPE
	BR	M.XA6		;REJOIN THE MAIN STREAM
M.XA1:	BGT	M.XA2		;IF GREATER THAN 0 DON'T NEGATE
	MOV	SP,R0		;SET UP THE REGISTERS TO
	MOV	R0,R1		;PREFORM THE NEGATION IN PLACE
	JSR	PC,NEGF		;NEGATE THE NUMBER
	BIS	#4,22(SP)	;BUT REMEMBER IT WAS NEGATIVE
M.XA2:	MOV	SP,R1		;OUR NUMBER IS THE SOURCE
	MOV	14(SP),R0	;10. IS THE DESTINATION
	JSR	PC,CMPF		;COMPARE FPN:10.
	BGE	M.XA4		;BRANCH IF OUT OF RANGE HIGH
M.XA3:	MOV	SP,R0		;OUR NUMBER IS NOW THE DESTINATION
	MOV	12(SP),R1	;1. IS THE SOURCE
	JSR	PC,CMPF		;COMPARE 1.:FPN
	BLE	M.XA5		;BRANCH IF IN RANGE
	MOV	SP,R0		;OUR NUMBER TO THE DESTINATION
	MOV	14(SP),R1	;10. IS THE SOURCE
	JSR	PC,MULF		;MULTIPLY BY 10.
	DEC	16(SP)		;DECREMENT THE DECIMAL EXPONENT
	BR	M.XA3		;REPEAT THE RANGE CHECK
M.XA4:	MOV	SP,R0		;OUR NUMBER TO THE DESTINATION
	MOV	14(SP),R1	;10. FOR A SOURCE
	JSR	PC,DIVF		;DIVIDE BY 10.
	INC	16(SP)		;INCREMENT DECIMAL EXPONENT
	BR	M.XA2		;REPEAT RANGE CHECK
M.XA5:	MOV	SP,R0		;OUR NUMBER IS THE DESTINATION
	MOV	10(SP),R1	;10.^7 IS THE SOURCE
	JSR	PC,MULF		;MULTIPLY TO GET 8 SIGNIFICANT FIGURES
	MOV	SP,R0		;OUR NUMBER TO GET ROUNDED
	MOV	6(SP),R1	;.5 IS THE OTHER OPERAND
	JSR	PC,ADDF		;ROUND OFF THE NUMBER
	MOV	SP,R0		;SET UP TO FIX THE
	MOV	R0,R1		;NUMBER IN PLACE
	JSR	PC,FIXD		;CONVERT TO INTEGER
	MOV	SP,R1		;OUR NUMBER IS TO BE THE SOURCE
	SUB	#14,SP		;PUT A TEMPORARY AREA ON THE STACK
	MOV	SP,R0		;STACK AS THE DESTINATION
	JSR	PC,JTOA		;CONVERT FRACTION TO ASCII STRING
	MOV	SP,R4		;USE ANOTHER REGISTER THAN SP
	ADD	#2,R4		;SKIP FIRST TWO SPACES
	CMPB	#040,@R4	;SEE IF WE HAVE A SPACE
	BEQ	M.XA7		;BRANCH WITH A SPACE
	INC	32(SP)		;MOVE THE DECIMAL BOINT
	BR	M.XA7+2		;PICK UP THE MAIN STREAM
M.XA7:	INC	R4		;GO TO POSITION THREE
	MOV	34(SP),R0	;PICK UP THE DEFA
	BIT	#4,36(SP)	;TEST FOR NEGATIVE
	BEQ	.+6		;->	;BRANCH IF PLUS
	MOVB	#055,@R0	;  I	;INSERT A MINUS SIGN
	ADD	#2,R0		;<-	;MOVE TO POSITION THREE
	MOV	#10,R3		;SET UP A COUNTER
	MOVB	(R4)+,(R0)+	;<-	;MOVE A BYTE
	DEC	R3		;  I	;DECREMENT COUNTER
	BGT	.-4		;->	;BRANCH IF NOT DONE
	ADD	#14,SP		;REMOVE TEMPORARY ASCII STRING
M.XA6:	ADD	#16,SP		;REMOVE OUR NUMBER AND TABLE OF ADDR
	INC	@SP		;CORRECT FOR 8 SIG FIGS
	BIT	#1,4(SP)	;TEST FOR TYPE OF CONVERSION
	BEQ	M.FA1		;BRANCH IF F CONVERSION
	MOV	SP,R1		;EXPONENT TO THE SOURCE
	SUB	#10,SP		;EXPAND THE STACK FOR ITOA
	MOV	SP,R0		;USE THE STACK FOR THE DESTINATION
	JSR	PC,ITOA		;CONVERT EXPONENT TO ASCII STRING
	MOV	12(SP),R0	;PICK UP THE DEFA
	INC	R0		;POP POINTER ONE POSITION
	MOVB	#056,@R0	;INSERT DECIMAL POINT
	ADD	#15,R0		;POINT JUST BEYOND THE END
	MOV	SP,R1		;BYTE OPERATIONS ON THE STACK
	ADD	#6,R1		;ARE MESSY SO USE ANOTHER REGISTER
	MOVB	-(R1),-(R0)	;MOVE UNITS POSITION OF EXPONENT
	MOVB	-(R1),-(R0)	;MOVE TENS POSITION OF EXPONENT
	MOVB	-(R1),-(R0)	;<-	;MOVE ANOTHER DIGIT
	CMPB	#57,@R1		;  I	;COMPARE FOR MORE DIGITS
	BLT	.-6		;->	;BRANCH IF A NUMBER
	MOVB	#105,-(R0)	;MOVE AN "E" TO THE STRING
	ADD	#16,SP		;ZOT THE STACK
	CLV			;CLEAR OVERFLOW ON A BIG MACHINE
	RTS	PC		;AND RETURN
M.FA1:	MOV	2(SP),R0	;PICK UP THE DEFA
	CMP	#10,@SP		;COMPARE DECIMAL EXPONENT WITH HIGH
	BLT	M.FAV		;BRANCH IF TOO BIG
	CMP	#-10,@SP	;COMPARE WITH LOWER BOUND
	BGE	M.FAV		;BRANCH IF TOO SMALL
	INC	R0		;MOVE TO POSITION TWO
	MOV	(SP)+,R3	;TEST DIRECTION OF THE SHIFT
	BGT	M.FA4		;BRANCH IF LEFT
	BMI	M.FA5		;BRANCH IF RIGHT
M.FA2:	MOVB	#056,@R0	;INSERT DECIMAL POINT
M.FA3:	CMP	(SP)+,(SP)+	;REMOVE ALL GOODIES
	CLV			;CLEAR OVERFLOW ON A REAL BIG MACHINE
	RTS	PC		;AND GO MAN GO
M.FA4:	MOVB	1(R0),(R0)+	;SHIF@ ONE DIGIT LEFT
	DEC	R3		;DECREMENT COUNT
	BGT	M.FA4		;BRANCH IF MORE TO DO
	BR	M.FA2		;INSERT DECIMAL AND EXIT
M.FA5:	MOVB	#056,@R0	;INSERT DECIMAL POINT
	MOV	#10,R2		;COMPUTE SIGNIFICANT DIGITS
	ADD	R3,R2		;WHICH IS 8-EXP
	ADD	#11,R0		;POINT TO THE END OF STRING + 1
	MOV	R0,R1		;COPY R0
	ADD	R3,R1		;POINT TO LEAST SIGNIFICANT DIGIT + 1
	MOVB	-(R1),-(R0)	;<-	;MOVE A DIGIT
	DEC	R2		;  I	;DECREMENT COUNTER
	BGT	.-4		;->	;BRANCH IF NOT DONE
	MOVB	#060,-(R0)	;<-	;INSERT 0'S
	INC	R3		;  I	;DECREMENT COUNTER
	BMI	.-6		;->	;BRANCH IF EVEN SMALLER
	BR	M.FA3		;AND WHEN DONE EXIT
M.FAV:	MOV	#12,R2		;PREPARE TO FILL THE OUTPUT
	MOVB	#052,(R0)+	;<-	;052=*
	DEC	R2		;  I	;DECREMENT COUNTER
	BGT	.-6		;->	;BRANCH IF NOT DONE
	ADD	#6,SP		;REMOVE ALL OUR JUNK
	SEV			;SET OVERFLOW FOR HIM
	RTS	PC		;AND OFF WE GO
	.EOT
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        